#include "../include/videoRecord.hpp"
#include "../include/Mylogger.hpp"
// 初始化FFmpeg


RTSPRecorder::~RTSPRecorder() {
    // 确保更新end_time
    time_t now = time(nullptr);
    wd::MySQLClient mysql;
    if (mysql.connect("127.0.0.1", 3306, "root", "1234", "3th") && !_currentFilePath.empty()) {
        char sql[256];
        sprintf(sql, "UPDATE videoRecord SET end_time = FROM_UNIXTIME(%ld) WHERE path = '%s' AND end_time IS NULL",
                now, _currentFilePath.c_str());
        mysql.writeOperationQuery(sql);
    }
    stopRecord();
}


#if 0
// 在 videoRecord.cc 中修改析构函数
RTSPRecorder::~RTSPRecorder() {
    if (_isRecording && !_currentFilePath.empty()) {
        // 计算实际的录像时长（开始时间到现在的时长）
        time_t now = time(nullptr);
        time_t actualDuration = now - _startTime;
        
        // 如果录像时间太短（比如小于10秒），可能是异常退出，删除记录
        if (actualDuration < 10) {
            wd::MySQLClient mysql;
            if (mysql.connect("127.0.0.1", 3306, "root", "1234", "3th")) {
                char sql[256];
                sprintf(sql, "DELETE FROM videoRecord WHERE path = '%s'", 
                        _currentFilePath.c_str());
                mysql.writeOperationQuery(sql);
                LOG_INFO("删除异常录像记录: " + _currentFilePath);
                
                // 同时删除文件
                remove(_currentFilePath.c_str());
            }
        } else {
            // 正常设置结束时间
            wd::MySQLClient mysql;
            if (mysql.connect("127.0.0.1", 3306, "root", "1234", "3th")) {
                char sql[256];
                sprintf(sql, "UPDATE videoRecord SET end_time = FROM_UNIXTIME(%ld) WHERE path = '%s'",
                        now, _currentFilePath.c_str());
                mysql.writeOperationQuery(sql);
            }
        }
    }
    stopRecord();
}
#endif

bool RTSPRecorder::initFFmpeg() {

    //av_register_all();
    avformat_network_init();

    // 打开RTSP流
    AVDictionary* options = nullptr;
    av_dict_set(&options, "rtsp_transport", "tcp", 0);
    av_dict_set(&options, "stimeout", "5000000", 0); // 5秒超时

    if (avformat_open_input(&_fmtCtx, _rtspUrl.c_str(), nullptr, &options) != 0) {

        LOG_ERROR("无法打开RTSP流: " + _rtspUrl);
        av_dict_free(&options);
        return false;
    }
    av_dict_free(&options);

    if (avformat_find_stream_info(_fmtCtx, nullptr) < 0) {
        LOG_ERROR("无法获取流信息");
        return false;
    }

    // 查找H.264视频流
    for (unsigned int i = 0; i < _fmtCtx->nb_streams; i++) {
        if (_fmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
            _fmtCtx->streams[i]->codecpar->codec_id == AV_CODEC_ID_H264) {
            _videoStreamIndex = i;
            break;
        }
    }

    if (_videoStreamIndex == -1) {
        LOG_ERROR("未找到H.264视频流");
        return false;
    }

    return true;
}


// 创建新的录像文件
bool RTSPRecorder::createNewFile() {
    // 生成文件名 (cameraId_时间戳.ts)
    time_t now = time(nullptr);
    struct tm* tm_info = localtime(&now);
    char filename[256];
    strftime(filename, sizeof(filename), "%Y%m%d%H%M%S", tm_info);
    string filePrefix = "recordings/" + _cameraId + "_" + filename;
    _currentFilePath = filePrefix + ".ts";

    // 创建输出上下文
    if (avformat_alloc_output_context2(&_outFmtCtx, nullptr, "mpegts", _currentFilePath.c_str()) < 0) {
        LOG_ERROR("无法创建输出上下文");
        return false;
    }

    // 复制流信息
    AVStream* inStream = _fmtCtx->streams[_videoStreamIndex];
    AVStream* outStream = avformat_new_stream(_outFmtCtx, nullptr);
    if (!outStream) {
        LOG_ERROR("无法创建输出流");
        return false;
    }

    if (avcodec_parameters_copy(outStream->codecpar, inStream->codecpar) < 0) {
        LOG_ERROR("无法复制流参数");
        return false;
    }
    outStream->codecpar->codec_tag = 0;

    // 打开输出文件
    if (!(_outFmtCtx->oformat->flags & AVFMT_NOFILE)) {
        if (avio_open(&_outFmtCtx->pb, _currentFilePath.c_str(), AVIO_FLAG_WRITE) < 0) {
            LOG_ERROR("无法打开输出文件: " + _currentFilePath);
            return false;
        }
    }

    // 写入文件头
    if (avformat_write_header(_outFmtCtx, nullptr) < 0) {
        LOG_ERROR("无法写入文件头");
        return false;
    }

    _currentFileSize = 0;
    _startTime = now;
    _currentPts = 0;

    // 记录到数据库
    wd::MySQLClient mysql;
    if (mysql.connect("127.0.0.1", 3306, "root", "1234", "3th")) {
        char sql[1024];
        sprintf(sql, "INSERT INTO videoRecord (name, start_time, camera_id, path) VALUES ('%s', FROM_UNIXTIME(%ld), '%s', '%s')",
                filename, now, _cameraId.c_str(), _currentFilePath.c_str());
        mysql.writeOperationQuery(sql);
    }

    return true;
}

// 处理流循环
void RTSPRecorder::processLoop() {
    AVPacket *pkt = av_packet_alloc();
    pkt->data = nullptr;
    pkt->size = 0;

    int64_t last_dts = AV_NOPTS_VALUE;


    while (_isRecording) {
        if (av_read_frame(_fmtCtx, pkt) < 0) {
            LOG_WARN("读取流数据失败，尝试重连");
            continue;
        }

        // 只处理视频流
        if (pkt->stream_index == _videoStreamIndex) {
            //修复时间戳问题
            if(pkt->dts != AV_NOPTS_VALUE){
                if(last_dts != AV_NOPTS_VALUE && pkt->dts <= last_dts){
                    //时间戳异常，调整或跳过
                    pkt->dts = last_dts + 1;
                    pkt->pts = pkt->dts;
                }
                last_dts = pkt->dts;
            }

            // 检查是否需要分片
            if (_currentFileSize > _maxFileSize || 
                (time(nullptr) - _startTime) > _maxDuration) {
                closeCurrentFile();
                createNewFile();
            }

            // 写入数据包
            AVPacket outPkt = *pkt;
            outPkt.stream_index = 0; // 输出只有一个流

            if (av_write_frame(_outFmtCtx, &outPkt) < 0) {
                LOG_WARN("写入数据包失败");
            } else {
                _currentFileSize += pkt->size;
                _currentPts = pkt->pts;
            }
        }
        av_packet_unref(pkt);
    }
}


// videoRecord.cc 补充实现
bool RTSPRecorder::startRecord() {
    if (_isRecording) {
        LOG_WARN("已在录像状态，无需重复启动");
        return true;
    }

    // 初始化FFmpeg
    if (!initFFmpeg()) {
        releaseFFmpeg();
        return false;
    }

    // 创建录像目录（若不存在）
    mkdir("recordings", 0755);

    // 创建第一个录像文件
    if (!createNewFile()) {
        releaseFFmpeg();
        return false;
    }

    _isRecording = true;
    // 启动后台线程处理流
    _recordThread = std::thread(&RTSPRecorder::processLoop, this);
    LOG_INFO("摄像头 " + _cameraId + " 开始录像");
    return true;
}

void RTSPRecorder::stopRecord() {
    if (!_isRecording) return;

    _isRecording = false;
    if (_recordThread.joinable()) {
        _recordThread.join(); // 等待录制线程结束
    }
    closeCurrentFile(); // 关闭最后一个文件
    releaseFFmpeg();
    LOG_INFO("摄像头 " + _cameraId + " 停止录像");
}

void RTSPRecorder::closeCurrentFile() {
    if (!_outFmtCtx) return;

    // 写入文件尾
    av_write_trailer(_outFmtCtx);

    // 关闭输出文件
    /* if (!(avformat_get_output_format(_outFmtCtx)->flags & AVFMT_NOFILE)) { */
    /*     avio_closep(&_outFmtCtx->pb); */
    /* } */

    // 关闭输出文件
    // 正确方式：直接访问输出格式上下文的oformat成员
    if (!(_outFmtCtx->oformat->flags & AVFMT_NOFILE)) {
        // 关闭输出IO上下文
        if (avio_closep(&_outFmtCtx->pb) < 0) {
            LOG_ERROR("关闭输出文件IO失败");
        }
    }

    // 更新数据库结束时间
    time_t endTime = time(nullptr);
    wd::MySQLClient mysql;
    if (mysql.connect("127.0.0.1", 3306, "root", "1234", "3th")) {
        char sql[1024];
        sprintf(sql, "UPDATE videoRecord SET end_time = FROM_UNIXTIME(%ld) WHERE path = '%s'",
                endTime, _currentFilePath.c_str());
        mysql.writeOperationQuery(sql);
    }

    // 释放输出上下文
    avformat_free_context(_outFmtCtx);
    _outFmtCtx = nullptr;
    LOG_INFO("已关闭录像文件: " + _currentFilePath);
}

void RTSPRecorder::releaseFFmpeg() {
    if (_fmtCtx) {
        avformat_close_input(&_fmtCtx);
        _fmtCtx = nullptr;
    }
    avformat_network_deinit();
}



